class webserialConnect{
    constructor(receiveSeparator = '|', sendSeparator = '', baudRate=115200){
        this.receiveSeparator = receiveSeparator
        this.sendSeparator = sendSeparator
        this.baudRate = baudRate
    }

    //overwrite this method to your implement.
    receive(msg){
        console.log(msg)
    }


    send(msg){
        return new Promise((resolve,reject) => {
            if(this.writer != null){
                this.writer.write(msg)
                .then(() => resolve())
                .catch(e => reject(e))
            }
            else{
                reject("not connected yet!")
            }
        })
    }

    connect(){
        return new Promise((resolve,reject) => {
            navigator.serial.requestPort()
            .then((port) => {
              this.port = port
              this.port.open({ baudRate: this.baudRate })
                .then(() => {
                  //initalize decoder and encoder,then start our "event loop"
                  this.decoder = new window.TextDecoderStream();
                  this.decoder_pipe = this.port.readable.pipeTo(this.decoder.writable);
                  this.reader = this.decoder.readable.getReader()
    
                  this.encoder = new window.TextEncoderStream();
                  this.encoder_pipe = this.encoder.readable.pipeTo(port.writable);
                  this.writer = this.encoder.writable.getWriter();
                  resolve()
                  this.serialEventLoop()
                })
                .catch(err => reject(err))
            })
            .catch(err => reject(err))
        })
    }

    disconnect(){
        this.cleanup()
    }

    async cleanup(){
        this.port_status = false
        this.reader.cancel()
        await this.decoder_pipe.catch(() => { /* Ignore the error */ });
        this.writer.close();
        await this.encoder_pipe;
        await this.port.close()
    }

    async serialEventLoop(){
        this.buffer = ""
        try {
            // we'd like to read it forever,so lets disable eslint for this line.
            // eslint-disable-next-line no-constant-condition
            while (true) {
              const { value, done } = await this.reader.read();
              if (done) {
                // Allow the serial port to be closed later.
                // this.reader.releaseLock();
                break;
              }
              if (value) {
                this.buffer += value;
                let index = this.buffer.indexOf(this.receiveSeparator)
                if(index >= 0){
                    let message = this.buffer.substring(null,index)
                    this.buffer = this.buffer.substring(index + 1)
                    this.receive(message)
                }
              }
            }
          } 
          catch (error) {
            console.log(error)
            this.cleanup()
          }
    }
}

module.exports = {
    webserialConnect
}